#include"MessageCodec.h"
#include<stdexcept>

using namespace std;

std::vector<uint8_t> MessageCodec::encode(MsgType type, const std::string& jsonBody)
{
    //转成字节流
    vector<uint8_t> ret;

    uint32_t bodyLen=jsonBody.size();

    uint16_t msgType=static_cast<uint16_t>(type);

    writeUint32(ret,bodyLen);
    writeUint16(ret,msgType);

    ret.insert(ret.end(),jsonBody.begin(),jsonBody.end());

    return ret;
}


std::vector<uint8_t> MessageCodec::encode(const LoginRequest& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::LOGIN_REQ, jsonStr);
}


std::vector<uint8_t> MessageCodec::encode(const LoginResponse& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::LOGIN_RES, jsonStr);
}


std::vector<uint8_t> MessageCodec::encode(const TextMessage& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::TEXT_MSG, jsonStr);
}

std::vector<uint8_t> MessageCodec::encode(const HeartBeat& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::HEARTBEAT, jsonStr);
}

std::vector<uint8_t> MessageCodec::encode(const GetFriendListRequest& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::GET_FRIEND_LIST_REQ, jsonStr);
}

std::optional<MessageHeader> MessageCodec::parseHeader(const uint8_t* data, size_t len)
{
    // 检查长度是否足够
    if(len < 6)
    {
        return std::nullopt;
    }

    MessageHeader header;
    
    // 读取长度（4字节）
    uint32_t netLen = readUint32(data);
    header.length = netLen;  // readUint32 内部已处理字节序
    
    // 读取类型（2字节）
    uint16_t netType = readUint16(data + 4);
    header.type = netType;    // readUint16 内部已处理字节序
    
    return header;
}

std::pair<MsgType, std::string> MessageCodec::decode(const std::vector<uint8_t>& data)
{
    auto headerOpt = parseHeader(data.data(), data.size());

    if(!headerOpt)
    {
        throw std::runtime_error("消息头解析失败");
    }

    MsgType type = static_cast<MsgType>(headerOpt->type);
    std::string json(data.begin() + sizeof(MessageHeader), data.begin() + sizeof(MessageHeader) + headerOpt->length);


    return {type, json};
    
}
 
std::string MessageCodec::toJson(const LoginRequest& msg)
{
    json j;
    j["username"] = msg.username;
    j["password"] = msg.password;
    return j.dump();
}

std::string MessageCodec::toJson(const LoginResponse& msg)
{
    json j;
    j["success"] = msg.success;
    j["message"] = msg.message;
    j["user_id"] = msg.user_id;
    j["username"] = msg.username;
    j["nickname"] = msg.nickname;
    j["avatar_url"] = msg.avatar_url;  // 头像URL
    j["token"] = msg.token;
    return j.dump();
}

std::string MessageCodec::toJson(const TextMessage& msg)
{
    json j;
    j["sender_id"] = msg.sender_id;
    j["receiver_id"] = msg.receiver_id;
    j["content"] = msg.content;
    j["timestamp"] = msg.timestamp;
    return j.dump();
}


std::string MessageCodec::toJson(const HeartBeat& msg)
{
    json j;
    j["timestamp"] = msg.timestamp;
    return j.dump();
}

std::string MessageCodec::toJson(const GetFriendListRequest& msg)
{
    json j;
    j["user_id"] = msg.user_id;
    return j.dump();
}

std::string MessageCodec::toJson(const FriendInfo& msg)
{
    json j;
    j["user_id"] = msg.user_id;
    j["username"] = msg.username;
    j["nickname"] = msg.nickname;
    j["avatar"] = msg.avatar;
    j["status"] = msg.status;
    return j.dump();
}

std::string MessageCodec::toJson(const GetFriendListResponse& msg)
{
    json j;
    j["success"] = msg.success;
    j["message"] = msg.message;
    
    json friendsArray = json::array();
    for (const auto& friend_info : msg.friends) {
        json friendJson;
        friendJson["user_id"] = friend_info.user_id;
        friendJson["username"] = friend_info.username;
        friendJson["nickname"] = friend_info.nickname;
        friendJson["avatar"] = friend_info.avatar;
        friendJson["status"] = friend_info.status;
        friendsArray.push_back(friendJson);
    }
    j["friends"] = friendsArray;
    
    return j.dump();
}

std::optional<LoginRequest> MessageCodec::loginRequestFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        LoginRequest msg;
        msg.username = j["username"].get<std::string>();
        msg.password = j["password"].get<std::string>();
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}

std::optional<LoginResponse> MessageCodec::loginResponseFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        LoginResponse msg;
        msg.success = j["success"].get<bool>();
        msg.message = j["message"].get<std::string>();
        msg.user_id = j["user_id"].get<uint64_t>();
        
        // 解析 username（可能为空）
        if (j.contains("username")) {
            msg.username = j["username"].get<std::string>();
        }
        
        // 解析 nickname（可能为空）
        if (j.contains("nickname")) {
            msg.nickname = j["nickname"].get<std::string>();
        }
        
        // 解析 avatar_url（可能为空）
        if (j.contains("avatar_url")) {
            msg.avatar_url = j["avatar_url"].get<std::string>();
        }
        
        msg.token = j["token"].get<std::string>();
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}

std::optional<TextMessage> MessageCodec::textMessageFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        TextMessage msg;
        msg.sender_id = j["sender_id"].get<uint64_t>();
        msg.receiver_id = j["receiver_id"].get<uint64_t>();
        msg.content = j["content"].get<std::string>();
        msg.timestamp = j["timestamp"].get<uint64_t>();
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}

std::optional<HeartBeat> MessageCodec::heartBeatFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        HeartBeat msg;
        msg.timestamp = j["timestamp"].get<uint64_t>();
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}

std::optional<GetFriendListRequest> MessageCodec::getFriendListRequestFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        GetFriendListRequest msg;
        msg.user_id = j["user_id"].get<uint64_t>();
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}

std::optional<FriendInfo> MessageCodec::friendInfoFromJson(const json& j)
{
    try {
        FriendInfo info;
        info.user_id = j["user_id"].get<uint64_t>();
        info.username = j["username"].get<std::string>();
        info.nickname = j.contains("nickname") ? j["nickname"].get<std::string>() : "";
        info.avatar = j.contains("avatar") ? j["avatar"].get<std::string>() : "";
        info.status = j.contains("status") ? j["status"].get<int>() : 0;
        return info;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}

std::optional<GetFriendListResponse> MessageCodec::getFriendListResponseFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        GetFriendListResponse msg;
        msg.success = j["success"].get<bool>();
        msg.message = j["message"].get<std::string>();
        
        if (j.contains("friends") && j["friends"].is_array()) {
            for (const auto& friendJson : j["friends"]) {
                auto friendOpt = friendInfoFromJson(friendJson);
                if (friendOpt) {
                    msg.friends.push_back(*friendOpt);
                }
            }
        }
        
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}


uint32_t MessageCodec::readUint32(const uint8_t* data)
{
    uint32_t ret;
    memcpy(&ret, data, sizeof(uint32_t));
    return ntohl(ret);  // 网络字节序 → 主机字节序
}

uint16_t MessageCodec::readUint16(const uint8_t* data)
{
    uint16_t ret;
    memcpy(&ret, data, sizeof(uint16_t));
    return ntohs(ret);  // 网络字节序 → 主机字节序
}

void MessageCodec::writeUint32(std::vector<uint8_t>& buf, uint32_t value)
{
    uint32_t netValue = htonl(value);

    const uint8_t* ptr = reinterpret_cast<const uint8_t*>(&netValue);

    buf.insert(buf.end(),ptr,ptr+sizeof(uint32_t));
}

void MessageCodec::writeUint16(std::vector<uint8_t>& buf, uint16_t value)
{
    uint16_t netValue = htons(value);

    const uint8_t* ptr = reinterpret_cast<const uint8_t*>(&netValue);

    buf.insert(buf.end(),ptr,ptr+sizeof(uint16_t));
}


std::string MessageCodec::toJson(const FileDownloadRequest& msg)
{
    json j;
    j["url"] = msg.url;
    j["save_name"] = msg.save_name;
    j["save_path"] = msg.save_path;
    return j.dump();
}

std::string MessageCodec::toJson(const FileDownloadResponse& msg)
{
    json j;
    j["success"] = msg.success;
    j["message"] = msg.message;
    j["file_path"] = msg.file_path;
    j["file_size"] = msg.file_size;
    return j.dump();
}

std::string MessageCodec::toJson(const FileDownloadProgress& msg)
{
    json j;
    j["file_name"] = msg.file_name;
    j["downloaded"] = msg.downloaded;
    j["total"] = msg.total;
    j["progress"] = msg.progress;
    return j.dump();
}


std::optional<FileDownloadRequest> MessageCodec::fileDownloadRequestFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        FileDownloadRequest msg;
        msg.url = j["url"].get<std::string>();
        msg.save_name = j["save_name"].get<std::string>();
        msg.save_path = j["save_path"].get<std::string>();
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}


std::optional<FileDownloadResponse> MessageCodec::fileDownloadResponseFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        FileDownloadResponse msg;
        msg.success = j["success"].get<bool>();
        msg.message = j["message"].get<std::string>();
        msg.file_path = j["file_path"].get<std::string>();
        msg.file_size = j["file_size"].get<uint64_t>();
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}


std::optional<FileDownloadProgress> MessageCodec::fileDownloadProgressFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        FileDownloadProgress msg;
        msg.file_name = j["file_name"].get<std::string>();
        msg.downloaded = j["downloaded"].get<uint64_t>();
        msg.total = j["total"].get<uint64_t>();
        msg.progress = j["progress"].get<uint32_t>();
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}

// ==================== 文件上传相关实现 ====================

// GetFriendListResponse 编码
std::vector<uint8_t> MessageCodec::encode(const GetFriendListResponse& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::GET_FRIEND_LIST_RES, jsonStr);
}

// FileUploadRequest 编码
std::vector<uint8_t> MessageCodec::encode(const FileUploadRequest& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::FILE_UPLOAD_REQ, jsonStr);
}

// FileUploadData 编码
std::vector<uint8_t> MessageCodec::encode(const FileUploadData& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::FILE_UPLOAD_DATA, jsonStr);
}

// FileUploadResponse 编码
std::vector<uint8_t> MessageCodec::encode(const FileUploadResponse& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::FILE_UPLOAD_RES, jsonStr);
}

// FileGetRequest 编码
std::vector<uint8_t> MessageCodec::encode(const FileGetRequest& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::FILE_GET_REQ, jsonStr);
}

// FileGetResponse 编码
std::vector<uint8_t> MessageCodec::encode(const FileGetResponse& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::FILE_GET_RES, jsonStr);
}

// FileDownloadRequest 编码
std::vector<uint8_t> MessageCodec::encode(const FileDownloadRequest& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::FILE_DOWNLOAD_REQ, jsonStr);
}

// FileDownloadResponse 编码
std::vector<uint8_t> MessageCodec::encode(const FileDownloadResponse& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::FILE_DOWNLOAD_RES, jsonStr);
}

// FileDownloadProgress 编码
std::vector<uint8_t> MessageCodec::encode(const FileDownloadProgress& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::FILE_DOWNLOAD_PROGRESS, jsonStr);
}

// FileUploadRequest → JSON
std::string MessageCodec::toJson(const FileUploadRequest& msg)
{
    json j;
    j["file_name"] = msg.file_name;
    j["file_type"] = msg.file_type;
    j["file_size"] = msg.file_size;
    return j.dump();
}

// FileUploadData → JSON
std::string MessageCodec::toJson(const FileUploadData& msg)
{
    json j;
    j["upload_id"] = msg.upload_id;
    j["chunk_index"] = msg.chunk_index;
    j["data"] = msg.data;
    j["is_last"] = msg.is_last;
    return j.dump();
}

// FileUploadResponse → JSON
std::string MessageCodec::toJson(const FileUploadResponse& msg)
{
    json j;
    j["success"] = msg.success;
    j["message"] = msg.message;
    j["upload_id"] = msg.upload_id;
    j["file_path"] = msg.file_path;
    j["file_url"] = msg.file_url;
    return j.dump();
}

// FileGetRequest → JSON
std::string MessageCodec::toJson(const FileGetRequest& msg)
{
    json j;
    j["file_path"] = msg.file_path;
    j["file_type"] = msg.file_type;
    j["user_id"] = msg.user_id;
    return j.dump();
}

// FileGetResponse → JSON
std::string MessageCodec::toJson(const FileGetResponse& msg)
{
    json j;
    j["success"] = msg.success;
    j["message"] = msg.message;
    j["file_name"] = msg.file_name;
    j["file_size"] = msg.file_size;
    j["data"] = msg.data;
    return j.dump();
}

// JSON → FileUploadRequest
std::optional<FileUploadRequest> MessageCodec::fileUploadRequestFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        FileUploadRequest msg;
        msg.file_name = j["file_name"].get<std::string>();
        msg.file_type = j["file_type"].get<std::string>();
        msg.file_size = j["file_size"].get<uint64_t>();
        
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}

// JSON → FileUploadData
std::optional<FileUploadData> MessageCodec::fileUploadDataFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        FileUploadData msg;
        msg.upload_id = j["upload_id"].get<std::string>();
        msg.chunk_index = j["chunk_index"].get<uint32_t>();
        msg.data = j["data"].get<std::string>();
        msg.is_last = j["is_last"].get<bool>();
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}

// JSON → FileUploadResponse
std::optional<FileUploadResponse> MessageCodec::fileUploadResponseFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        FileUploadResponse msg;
        msg.success = j["success"].get<bool>();
        msg.message = j["message"].get<std::string>();
        
        // 可选字段
        if (j.contains("upload_id")) {
            msg.upload_id = j["upload_id"].get<std::string>();
        }
        if (j.contains("file_path")) {
            msg.file_path = j["file_path"].get<std::string>();
        }
        if (j.contains("file_url")) {
            msg.file_url = j["file_url"].get<std::string>();
        }
        
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}

// JSON → FileGetRequest
std::optional<FileGetRequest> MessageCodec::fileGetRequestFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        FileGetRequest msg;
        msg.file_path = j["file_path"].get<std::string>();
        msg.file_type = j["file_type"].get<std::string>();
        msg.user_id = j["user_id"].get<uint64_t>();
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}

// JSON → FileGetResponse
std::optional<FileGetResponse> MessageCodec::fileGetResponseFromJson(const std::string& jsonStr)
{
    try {
        json j = json::parse(jsonStr);
        FileGetResponse msg;
        msg.success = j["success"].get<bool>();
        msg.message = j["message"].get<std::string>();
        
        // 可选字段
        if (j.contains("file_name")) {
            msg.file_name = j["file_name"].get<std::string>();
        }
        if (j.contains("file_size")) {
            msg.file_size = j["file_size"].get<uint64_t>();
        }
        if (j.contains("data")) {
            msg.data = j["data"].get<std::string>();
        }
        
        return msg;
    } catch (const json::exception& e) {
        return std::nullopt;
    }
}

// ==================== 好友状态通知 ====================

// FriendStatusNotify 编码
std::vector<uint8_t> MessageCodec::encode(const FriendStatusNotify& msg)
{
    std::string jsonStr = toJson(msg);
    return encode(MsgType::FRIEND_STATUS_NOTIFY, jsonStr);
}

// FriendStatusNotify → JSON
std::string MessageCodec::toJson(const FriendStatusNotify& msg)
{
    json j;
    j["user_id"] = msg.user_id;
    j["status"] = msg.status;
    j["timestamp"] = msg.timestamp;
    return j.dump();
}


